Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> SQL Injection/Insertion, Jak zapobiec włamaniu na stronę.
Najki
post
Post #1





Grupa: Zarejestrowani
Postów: 190
Pomógł: 0
Dołączył: 12.02.2004
Skąd: Poznań

Ostrzeżenie: (0%)
-----


Pytania o streszczenie wątku, posty z "genialnymi" skryptami nadającymi się tylko na przedszkole i inne tego typu, będą bez ostrzeżenia usuwane przez moderatorów.
To mówiłem ja, Jarząbek... znaczy nospor dnia 2007-12-10
-------------------------------------------------------------------------------


SQL Injection (zwane też "SQL Insertion") to (rzekomo) najprostszy sposób włamu na stronę. Spowodowany jest on niepełnym sformułowaniem zapytań do MySQL.

Przykład. Dajemy na stronie możliwość edycji profilu. Zapytanie do SQL wygląda następująco:
  1. <?php
  2. $query = &#092;"update uzytkownicy set pole='$dane' where id='$id'\";
  3. ?>

Osoba włamująca się na stronę umieszcza całkiem prosty, odpowiedni ciąg znaków/poleceń w dowolnym polu edycji tego profilu, który wygląda np. tak (dla zmiany hasła użytkownika o dowolnie wybranym, przez atakującego numerze ID):
  1. <?php
  2. ', haslo='nowe_haslo' WHERE id = '1
  3. ?>


W taki oto prosty sposób, osoba atakująca zmieniła hasło użytkownikowi o ID=1 (zazwyczaj administrator). W podobny sposób można również wyciągnąć dowolne dane z tabeli SQL.

W każdym razie. Poszperałem, pomyślałem i zebrałem wszystko do kupy. Zamieszczam to tutaj razem, oraz proszę o rozbudowanie tego topica, gdyż nie znalazłem na tym forum więcej informacji o "SQL Injection".

Oto co możemy dokonać:
1. Możemy sformułować nasze zapytanie do SQL tak:
  1. <?php
  2. $query = 'update `uzytkownicy` set `pole`=\"'.$dane.'\" where `id`=\"'.$id.'\";';
  3. ?>

2. Przy wstawianiu numerów ID do zapytań należy stosować tzw. rzutowanie typów:
  1. <?php
  2. $id = (int)$_GET['id'];
  3. // lub
  4. $id = intval($_GET['id']);
  5. ?>

3. Przy wstawianiu tekstów, należy wyciąć niebezpieczne znaki przy pomocy funkcji:
  1. <?php
  2. $string = mysql_real_escape_string($_POST['string']); // PHP5
  3.  
  4. $string = mysql_escape_string($_POST['string']); /* lub */ $string = addslashes($_POST['string']); // PHP4
  5. ?>


Może nie ma tego dużo, ale jest to już jakaś podstawa do zabezpieczenia strony/skryptu przed prostym i niezwykle niebezpiecznym, SQL Injection. Proszę osoby obeznane w tym temacie, aby dopisały tu własne propozycje metod zabezpieczenia się przed tym atakiem.

Ten post edytował Najki 14.02.2008, 10:04:12
Go to the top of the page
+Quote Post
22 Stron V  « < 18 19 20 21 22 >  
Start new topic
Odpowiedzi (380 - 399)
Dominator
post
Post #381





Grupa: Zarejestrowani
Postów: 565
Pomógł: 15
Dołączył: 11.10.2010

Ostrzeżenie: (20%)
X----


Jeśli będę używał PDO zamiast MySQL do łączenia się z bazą danych to jest mniejsze prawdopodobieństwo, że ktoś może wykorzystać SQL Injection ?
Go to the top of the page
+Quote Post
Mephistofeles
post
Post #382





Grupa: Zarejestrowani
Postów: 1 182
Pomógł: 115
Dołączył: 4.03.2009
Skąd: Myszków

Ostrzeżenie: (0%)
-----


Po pierwsze nie zamiast MySQL, co najwyżej mysql_ (IMG:style_emoticons/default/smile.gif) .
Po drugie tylko jeśli będziesz używał zapytań preparowanych i podpinania parametrów, wtedy prawdopodobieństwo -> 0.

Ten post edytował Mephistofeles 14.07.2012, 22:46:02
Go to the top of the page
+Quote Post
Dominator
post
Post #383





Grupa: Zarejestrowani
Postów: 565
Pomógł: 15
Dołączył: 11.10.2010

Ostrzeżenie: (20%)
X----


A gdzie mogę zobaczyć przykład zapytań preparowanych ?
Go to the top of the page
+Quote Post
Mephistofeles
post
Post #384





Grupa: Zarejestrowani
Postów: 1 182
Pomógł: 115
Dołączył: 4.03.2009
Skąd: Myszków

Ostrzeżenie: (0%)
-----


Stronę wcześniej w tym temacie (IMG:style_emoticons/default/biggrin.gif) .
Go to the top of the page
+Quote Post
Dominator
post
Post #385





Grupa: Zarejestrowani
Postów: 565
Pomógł: 15
Dołączył: 11.10.2010

Ostrzeżenie: (20%)
X----


Czyli ten kod jest preparowaniem zmiennych, tak ?

  1. $pdo = new PDO("mysql:host=localhost;dbanme=xxx", "root", "");
  2. $zap = $pdo->prepare("INSERT INTO `uzytkownicy` (`login`, `haslo`, `email`) VALUES(:login, :haslo, :email)");
  3. $zap->bindValue(":login", $_POST['login'], PDO::PARAM_STR);
  4. $zap->bindValue(":haslo", $_POST['haslo'], PDO::PARAM_STR);
  5. $zap->bindValue(":email", $_POST['email'], PDO::PARAM_STR);
  6. $zap->execute();
  7. $zap->closeCursor();
Go to the top of the page
+Quote Post
d3ut3r
post
Post #386





Grupa: Zarejestrowani
Postów: 709
Pomógł: 176
Dołączył: 24.10.2010

Ostrzeżenie: (0%)
-----


tak.
Go to the top of the page
+Quote Post
Dominator
post
Post #387





Grupa: Zarejestrowani
Postów: 565
Pomógł: 15
Dołączył: 11.10.2010

Ostrzeżenie: (20%)
X----


Dobra, po przeczytaniu lektury w tym temacie od dnia dzisiejszego będę korzystał z PDO.

Dzięki (IMG:style_emoticons/default/smile.gif)

A w jaki bezpieczny sposób wyciągać dane użytkowników za pomocą PDO ?
Go to the top of the page
+Quote Post
Cadmer
post
Post #388





Grupa: Zarejestrowani
Postów: 4
Pomógł: 0
Dołączył: 21.01.2013

Ostrzeżenie: (0%)
-----


Witam
Chciałbym potwierdzić kilka rzeczy:
1. Czy funkcja mysqli_real_escape_string jest tak samo nic niewarta jak mysql_real_escape_string? Oczywiście na dzień dzisiejszy (PHP 5.4).
2. Czy w przypadku liczb całkowitych rzutowanie na inta jest wystarczającym zabezpieczeniem czy są jakieś cudowne metody pozwalające obejść to?
3. Czy htmlentities chroni przed XSS?
I od razu chciałbym zaznaczyć że nie jestem upartym durniem broniącym się rękami i nogami przez używaniem prepared statements, tylko jakiś czas temu przeczytałem to i stwierdzenie tam zawarte nie daje mi spokoju:
Cytat
SQL injections are not the reason to write slower code, php mysql driver provides several ways to escape the input.
Go to the top of the page
+Quote Post
pyro
post
Post #389





Grupa: Zarejestrowani
Postów: 2 148
Pomógł: 230
Dołączył: 26.03.2008

Ostrzeżenie: (0%)
-----


Cytat(Cadmer @ 21.01.2013, 22:12:19 ) *
1. Czy funkcja mysqli_real_escape_string jest tak samo nic niewarta jak mysql_real_escape_string? Oczywiście na dzień dzisiejszy (PHP 5.4).


Obie są stworzone do tego, co mają robić, i stwierdzenie, że są nic nie warte to pitolenie po całości.

Cytat(Cadmer @ 21.01.2013, 22:12:19 ) *
2. Czy w przypadku liczb całkowitych rzutowanie na inta jest wystarczającym zabezpieczeniem czy są jakieś cudowne metody pozwalające obejść to?


Wystarczy

Cytat(Cadmer @ 21.01.2013, 22:12:19 ) *
3. Czy htmlentities chroni przed XSS?


Między innymi tak.
Go to the top of the page
+Quote Post
Cadmer
post
Post #390





Grupa: Zarejestrowani
Postów: 4
Pomógł: 0
Dołączył: 21.01.2013

Ostrzeżenie: (0%)
-----


Dzięki z szybką i konkretną odpowiedz.
Co do 1. to chyba zostałem źle zrozumiany też wydaje mi się (bo brak mi wiedzy na ten temat) że te funkcja działa jak powinna, lecz wcześniej w tym wątku, albo gdzieś indziej, wyczytałem że ma problemy z kodowaniem znaków itp. itd.
To jeszcze tak dla pewności - używanie mysqli_real_escape_string jest tak samo efektywne (albo chociaż porównywalne) z używaniem prepared statements? Oczywiście jeśli chodzi o zabezpieczenie przez SQL Injection.
Go to the top of the page
+Quote Post
pyro
post
Post #391





Grupa: Zarejestrowani
Postów: 2 148
Pomógł: 230
Dołączył: 26.03.2008

Ostrzeżenie: (0%)
-----


Cytat(Cadmer @ 21.01.2013, 23:19:03 ) *
Dzięki z szybką i konkretną odpowiedz.
Co do 1. to chyba zostałem źle zrozumiany też wydaje mi się (bo brak mi wiedzy na ten temat) że te funkcja działa jak powinna, lecz wcześniej w tym wątku, albo gdzieś indziej, wyczytałem że ma problemy z kodowaniem znaków itp. itd.
To jeszcze tak dla pewności - używanie mysqli_real_escape_string jest tak samo efektywne (albo chociaż porównywalne) z używaniem prepared statements? Oczywiście jeśli chodzi o zabezpieczenie przez SQL Injection.


Musisz przeczytać do czego służy jedno i drugie... bo jak w ciemno będziesz wszędzie stosował "funkcje zabezpieczające" nie rozumiejąc co one robią, to prawdopodobnie i tak zostawisz luki, pomimo ich zastosowania.
Go to the top of the page
+Quote Post
Cadmer
post
Post #392





Grupa: Zarejestrowani
Postów: 4
Pomógł: 0
Dołączył: 21.01.2013

Ostrzeżenie: (0%)
-----


Na dobrą sprawę moim problemem nie jest niewiedza jeśli chodzi o techniki obrony przed SQL Injection, chodzi bardziej o to że nie mam pojęcia jak wygląda taki atak (hakowanie mnie kompletnie nie interesuje), oczywiście poza teorią i prostymi przykładami - tylko jak dla mnie przed tym chroniło magic quotes, a tu czytam że w 5.4 zostało praktycznie rzecz ujmując wywalone. Przez co trochę zgłupiałem.
Ale poczytałem na spokojnie i rozwiałem większość swoich wątpliwości. Swoją drogą polecam tą stronę - wszystko w jednym miejscu i konkretnie na temat.
Mam jeszcze dwa pytania na które nie znalazłem konkretnych odpowiedzi.
W przypadku gdy chcę umieścić w bazie treść np. komentarza, posta, wiadomości itp. czyli gdy jest duża dowolność wpisywanych danych oraz ma być to później wyświetlone. Widzę dwa rozwiązania:
1. Zdekodować taką treść używając htmlentities i zapisać w takiej postaci w bazie. Niby nie jest to złe rozwiązanie ale ciężko będzie takie coś edytować z poziomu bazy danych.
2. Zastosować przed umieszczaniem w bazie mysqli_real_escape_string, a przy wyświetleniu użyć htmlentities. Nie ma to wady pierwszej metody ale nie jestem pewien czy samo mysqli_real_escape_string wystarczy.
Czy do switcha można wystrzyknąć złośliwy kod? Czyli czy takie coś:
  1. switch($_GET['cos'])
  2. { ... }

jest potencjalnie niebezpieczne? Wiem że to ogólnie zła praktyka bo uczy złych nawyków, ale chodzi mi konkretnie czy switch jest narażony na taki atak.

Ten post edytował Cadmer 22.01.2013, 17:50:25
Go to the top of the page
+Quote Post
pyro
post
Post #393





Grupa: Zarejestrowani
Postów: 2 148
Pomógł: 230
Dołączył: 26.03.2008

Ostrzeżenie: (0%)
-----


Cytat(Cadmer @ 22.01.2013, 17:49:30 ) *
W przypadku gdy chcę umieścić w bazie treść np. komentarza, posta, wiadomości itp. czyli gdy jest duża dowolność wpisywanych danych oraz ma być to później wyświetlone. Widzę dwa rozwiązania:
1. Zdekodować taką treść używając htmlentities i zapisać w takiej postaci w bazie. Niby nie jest to złe rozwiązanie ale ciężko będzie takie coś edytować z poziomu bazy danych.
2. Zastosować przed umieszczaniem w bazie mysqli_real_escape_string, a przy wyświetleniu użyć htmlentities. Nie ma to wady pierwszej metody ale nie jestem pewien czy samo mysqli_real_escape_string wystarczy.


1 metoda odpada zupełnie, bo jest to bardzo zła praktyka, jeśli chodzi o cały projekt.

Co do reszty, przeanalizuj poniższy przykład:

  1. <?php
  2.  
  3. // ....
  4.  
  5. $user_id = $_GET['user_id'];
  6. $result = mysql_query('SELECT * FROM users WHERE id = '.mysql_real_escape_string($user_id));
  7.  
  8. // .....
  9.  
  10. ?>


I sam mi odpowiedz na pytanie czemu ten urywek kodu jest podatny na ataki.

Cytat(Cadmer @ 22.01.2013, 17:49:30 ) *
Czy do switcha można wystrzyknąć złośliwy kod? Czyli czy takie coś:
  1. switch($_GET['cos'])
  2. { ... }

jest potencjalnie niebezpieczne? Wiem że to ogólnie zła praktyka bo uczy złych nawyków, ale chodzi mi konkretnie czy switch jest narażony na taki atak.


To też zależy. Z reguły nie, ale w przypadku udziwniania, też można zostawić lukę pozwalającą na włamanie.
Go to the top of the page
+Quote Post
Cadmer
post
Post #394





Grupa: Zarejestrowani
Postów: 4
Pomógł: 0
Dołączył: 21.01.2013

Ostrzeżenie: (0%)
-----


Cóż można tam wstawić ID jakiegokolwiek użytkownika, co niekoniecznie jest błędem zależy co miałby ten kod robić. Nie powinno się raczej nigdy za to wybierać wszystkich kolumn z tabeli przy pomocy * z wielu powodów. Jeśli chodziło Ci o coś innego to tak jak pisałem wcześniej nie znam się na magicznych jak dla mnie sposobach wczepiania kodu zapytań.
Go to the top of the page
+Quote Post
Piotrbaz
post
Post #395





Grupa: Zarejestrowani
Postów: 55
Pomógł: 2
Dołączył: 15.09.2012

Ostrzeżenie: (0%)
-----


Cytat(pyro @ 22.01.2013, 18:08:50 ) *
1 metoda odpada zupełnie, bo jest to bardzo zła praktyka, jeśli chodzi o cały projekt.



Mógłbyś jakoś rozwinąć ? Właśnie jestem na etapie 'zabezpieczania' danych z postów i komentarzy i miałem zamiar użyć htmlspecialchars lub htmlentities. Oczywiście nie w kontekście SQL Injection, bo od tego mam PDO, ale np ataków XSS.

Ten post edytował Piotrbaz 3.02.2013, 18:07:07
Go to the top of the page
+Quote Post
pyro
post
Post #396





Grupa: Zarejestrowani
Postów: 2 148
Pomógł: 230
Dołączył: 26.03.2008

Ostrzeżenie: (0%)
-----


Cytat(Cadmer @ 22.01.2013, 22:22:41 ) *
Cóż można tam wstawić ID jakiegokolwiek użytkownika, co niekoniecznie jest błędem zależy co miałby ten kod robić. Nie powinno się raczej nigdy za to wybierać wszystkich kolumn z tabeli przy pomocy * z wielu powodów. Jeśli chodziło Ci o coś innego to tak jak pisałem wcześniej nie znam się na magicznych jak dla mnie sposobach wczepiania kodu zapytań.


Nie, zupełnie nie o to chodzi. Jako user_id podstaw sobie (zakładam, że w tabeli są kolumny id, username, password):

Kod
-1 UNION SELECT 1, DATABASE(), 3


I zobacz co się stanie. Zabezpieczone przez mysql_real_escape_string(), a luka nadal jest. Magia, co?


Cytat(Piotrbaz @ 3.02.2013, 18:05:56 ) *
Mógłbyś jakoś rozwinąć ? Właśnie jestem na etapie 'zabezpieczania' danych z postów i komentarzy i miałem zamiar użyć htmlspecialchars lub htmlentities. Oczywiście nie w kontekście SQL Injection, bo od tego mam PDO, ale np ataków XSS.


Dane do wyświetlania zabezpiecza się właśnie przy wyświetlaniu, a nie ładuje do bazy już w zmienionej formie. Chodzi o integralność danych i czytelność tego co wpisują użytkownicy.

Ten post edytował pyro 3.02.2013, 21:42:13
Go to the top of the page
+Quote Post
Piotrbaz
post
Post #397





Grupa: Zarejestrowani
Postów: 55
Pomógł: 2
Dołączył: 15.09.2012

Ostrzeżenie: (0%)
-----


No ok, czyli htmlspecialchars() stosuje przed wyświetleniem danych użytkownikowi. Czy przed zapisem danych do bazy ograniczam się tylko zabezpieczeniem przed SQL Injection ? (co załatwia podpinanie w PDO)

Ten post edytował Piotrbaz 3.02.2013, 23:12:03
Go to the top of the page
+Quote Post
pyro
post
Post #398





Grupa: Zarejestrowani
Postów: 2 148
Pomógł: 230
Dołączył: 26.03.2008

Ostrzeżenie: (0%)
-----


Tak, prepared statements w PDO powinny załatwić sprawę. No chyba że integer przez przypadek potraktujesz jako string.

Ten post edytował pyro 3.02.2013, 23:19:18
Go to the top of the page
+Quote Post
Wasper
post
Post #399





Grupa: Zarejestrowani
Postów: 82
Pomógł: 1
Dołączył: 18.09.2011

Ostrzeżenie: (0%)
-----


Czesc,

troche tego duzo, szczerze, nie mam czasu czytac wszystkich stron.Ale mam pytanie apropo mysql_real_escape_string.
Wszyscy pisza, zeby uzywac do zmiennych przed wstawieniem do zapytania...
a nie mozna finalnego zapytania w calosci przepuscic przez to? Czy to bedzie mialo jakis nieoczekiwany efekt?
Go to the top of the page
+Quote Post
!*!
post
Post #400





Grupa: Zarejestrowani
Postów: 4 298
Pomógł: 447
Dołączył: 16.11.2006

Ostrzeżenie: (0%)
-----


Zostaw te bzdury zaczynające się od mysql_* w manualu i przejdź na PDO, a nie będziesz mieć takich problemów.
Go to the top of the page
+Quote Post

22 Stron V  « < 18 19 20 21 22 >
Reply to this topicStart new topic
2 Użytkowników czyta ten temat (2 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Aktualny czas: 23.08.2025 - 21:25